package niu.toy.spring.support;

import cn.hutool.core.util.ArrayUtil;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;

/**
 * 处理泛型参数相关
 */
public class TypeHelper {
    private Type type;
    public TypeHelper(Type type){
        this.type=type;
    }
    public Type getType(){
        return this.type;
    }
    public Type getMapKeyType(int nestingLevel) {
        return getGenerics(nested(nestingLevel))[0];
    }

    public Type getMapValueType(int nestingLevel) {
        return getGenerics(nested(nestingLevel))[1];
    }

    public Type getMapValueSubType(int nestingLevel) {
        return getGenerics(getGenerics(nested(nestingLevel))[1])[0];
    }
    public Type getValueSubType(int nestingLevel) {
        return getGenerics(nested(nestingLevel))[0];
    }
    public static Type  getSubType(Type type) {
        return getGenerics(type)[0];
    }
    public Type getCollectionType(int nestingLevel) {
        return  getGenerics(nested(nestingLevel))[0];
    }
    public Type  nested(int nestingLevel){
        Type result=getType();
        for (int i = 2; i <= nestingLevel; i++) {
            if (result.getClass().isArray()) {
                result = result.getClass().getComponentType();
            }
            else {
                if (result instanceof ParameterizedType) {
                    Type[] actualTypeArguments = ((ParameterizedType) result).getActualTypeArguments();
                    result = actualTypeArguments[actualTypeArguments.length - 1];
                }else{
                    result=null;
                    break;
                }
            }
        }
        return result;
    }
    public Type[] getGenerics() {
        return this.getGenerics(this.type);
    }
    public static Type[] getGenerics(Type type) {
//        if(type){
//            TypeUtil.getTypeArgument()
//            if (result.isArray()) {
//                result = result.getComponentType();
//                Class<?> componentType = type.getComponentType();
//            }
//        }
        if (type instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
            return actualTypeArguments;
        }else{
            return ArrayUtil.toArray(Arrays.asList(type),Type.class);
        }
    }
}
